package com.huaxin.hxmoduleworkorder.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huaxin.feignclient.system.models.ElectricianArchives;
import com.huaxin.feignclient.system.models.User;
import com.huaxin.hxmoduleworkorder.common.UserContext;
import com.huaxin.hxmoduleworkorder.common.enums.*;
import com.huaxin.hxmoduleworkorder.dto.ResponseResult;
import com.huaxin.hxmoduleworkorder.dto.request.*;
import com.huaxin.hxmoduleworkorder.dto.response.MaintenanceOrderDetailRespDto;
import com.huaxin.hxmoduleworkorder.feignclients.SysFeignService;
import com.huaxin.hxmoduleworkorder.mapper.MaintenanceOrderMapper;
import com.huaxin.hxmoduleworkorder.mapping.MaintenanceOrderMapping;
import com.huaxin.hxmoduleworkorder.models.MaintenanceOrder;
import com.huaxin.hxmoduleworkorder.models.MaintenanceOrderElectricianTask;
import com.huaxin.hxmoduleworkorder.models.MaintenanceOrderProcess;
import com.huaxin.hxmoduleworkorder.service.MaintenanceOrderElectricianTaskService;
import com.huaxin.hxmoduleworkorder.service.MaintenanceOrderProcessService;
import com.huaxin.hxmoduleworkorder.service.MaintenanceOrderService;
import com.huaxin.hxmoduleworkorder.service.OrderNotificationService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.webjars.NotFoundException;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Consumer;

@Service
@RequiredArgsConstructor
public class MaintenanceOrderServiceImpl extends ServiceImpl<MaintenanceOrderMapper, MaintenanceOrder> implements MaintenanceOrderService {
    private final ApplicationContext applicationContext;
    private final MaintenanceOrderMapping mapping;
    private final MaintenanceOrderElectricianTaskService electricianTaskService;
    private final MaintenanceOrderProcessService processService;
    private final ApplicationEventPublisher eventPublisher; // 用于发布事件（如通知）
    private final SysFeignService sysFeignService;
    private final OrderNotificationService orderNotificationService;

    /* *********************************************************************
     * 工单基础 CRUD 操作
     ********************************************************************* */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<MaintenanceOrder> create(MaintenanceOrderCreateReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数不能为空");
        }

        MaintenanceOrder order = mapping.toEntity(in);
        this.save(order);

        // 记录创建流程
        processService.create(MaintenanceOrderProcessCreateReqDTO.builder()
                .MaintenanceOrderId(order.getId())
                .action(MaintenanceOrderOperation.CREATE)
                .fromStatus(MaintenanceOrderStatus.UNKNOWN)
                .toStatus(MaintenanceOrderStatus.CREATED)
                .operatorRole(MaintenanceOrderOperatorRole.of(in.getCreatedByRole()))
                .operatorId(UserContext.getCurrentUserId())
                .operatorLongitude(in.getCreatedByLongitude())
                .operatorLatitude(in.getCreatedByLatitude())
                .remarks("创建工单：" + in.getTitle())
                .isCompleted(1)
                .build());

        this.submit(MaintenanceOrderSubmitReqDto.builder()
                .orderId(order.getId())
                .operatorRole(in.getCreatedByRole())
                .operatorLongitude(in.getCreatedByLongitude())
                .operatorLatitude(in.getCreatedByLatitude())
                .remarks("提交工单：" + in.getTitle())
                .build());

        MaintenanceOrder created = this.getById(order.getId());
        return ResponseResult.ok(created);
    }

    @Override
    public MaintenanceOrder getOrderById(String id) {
        if (StringUtils.isBlank(id)) {
            throw new IllegalArgumentException("工单ID不能为空");
        }
        MaintenanceOrder order = this.getById(id);
        if (order == null) {
            throw new NotFoundException("工单不存在");
        }
        return order;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<String> update(MaintenanceOrderUpdateReqDTO in) {
        MaintenanceOrder order = this.getOrderById(in.getOrderId());
        if (!canOperate(order.getId(), MaintenanceOrderOperation.EDIT, in.getOperatorRole())) {
            throw new IllegalStateException("当前状态不允许修改：" + order.getStatus());
        }
        mapping.updateEntity(in, order);
        this.updateById(order);

        this.submit(MaintenanceOrderSubmitReqDto.builder()
                .orderId(order.getId())
                .operatorRole(in.getOperatorRole())
                .operatorLongitude(in.getOperatorLongitude())
                .operatorLatitude(in.getOperatorLatitude())
                .remarks("提交工单：" + in.getTitle())
                .build());

        return ResponseResult.ok("更新成功！");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<String> delete(MaintenanceOrderDeleteReqDto in) {
        MaintenanceOrder order = this.getOrderById(in.getOrderId());
        if (!canOperate(order.getId(), MaintenanceOrderOperation.DELETE, in.getOperatorRole())) {
            throw new IllegalStateException("当前状态不允许删除：" + order.getStatus());
        }
        applicationContext.getBean(MaintenanceOrderService.class).removeById(in.getOrderId());

        // 删除工单关联的电工任务
        electricianTaskService.deleteByOrderId(in.getOrderId());

        return ResponseResult.ok("删除成功！");
    }

    /* *********************************************************************
     * 工单状态与流程管理
     ********************************************************************* */

    @Override
    public ResponseResult<String> getOrderStatus(String id) {
        MaintenanceOrder order = this.getOrderById(id);
        return ResponseResult.ok(order.getStatus().getCode());
    }


    /*----------------------------------------------------------------------------------------------------------------*/

    /*
     * 工单操作权限控制
     * 操作       角色                 允许的状态                            说明
     * edit     创建人                created                              草稿或被退回时可编辑
     * submit   创建人                created                              编辑后提交
     * cancel   创建人、管理员          reviewing, assigned, processing     审核中及之后可取消
     * evaluate 客户                  resolved, completed                  解决后可评价
     * review   管理员                reviewing                            待审核状态
     * assign   管理员                reviewing                            分配，已在审核时执行分配
     * reject   管理员、主修电工        reviewing, assigned, processing      可驳回给客户
     * reassign 管理员、主修电工        assigned, reassigned, processing       重新分配电工
     * view     管理员、电工           所有                                  所有人可查看自己相关的工单
     * rollback 管理员                reviewing                            退回至创建
     * rollback 管理员                resolved                             退回至分配
     * delete   管理员                rejected, cancelled                  删除工单
     */

    /**
     * 根据工单当前状态和用户角色，返回可执行的操作列表
     *
     * @return 可执行的操作列表
     */
    @Override
    public List<MaintenanceOrderOperation> getAvailableOperations(String orderId, MaintenanceOrderOperatorRole operatorRole) {
        if (orderId == null || operatorRole == null) {
            return List.of();
        }
        MaintenanceOrder order = this.getById(orderId);
        return this.getAvailableOperations(order, operatorRole);
    }

    private List<MaintenanceOrderOperation> getAvailableOperations(MaintenanceOrder order, MaintenanceOrderOperatorRole operatorRole) {
        if (order == null) {
            return List.of();
        }

        MaintenanceOrderStatus status = order.getStatus();

        if (status == null || operatorRole == null) {
            return List.of();
        }

        String currentUserId = UserContext.getCurrentUserId();
        if (StringUtils.isBlank(currentUserId)) {
            return List.of();
        }

        List<MaintenanceOrderOperation> operations = new ArrayList<>();

        boolean isCreator = order.getCreatedBy().equals(currentUserId);
        boolean isCustomer = MaintenanceOrderOperatorRole.CUSTOMER.equals(operatorRole) && order.getCustomerId().equals(currentUserId);
        boolean isAdmin = MaintenanceOrderOperatorRole.ADMIN.equals(operatorRole);
        boolean isElectrician = MaintenanceOrderOperatorRole.ELECTRICIAN.equals(operatorRole) && electricianTaskService.isAssigned(order.getId(), currentUserId);

        // 工单创建人、管理员、电工可查看工单
        if (isCreator || isAdmin || isElectrician) {
            operations.add(MaintenanceOrderOperation.VIEW);
        }

        boolean isLeadElectrician = MaintenanceOrderOperatorRole.ELECTRICIAN.equals(operatorRole) && order.getElectricianId().equals(currentUserId);
        switch (status) {
            case CREATED:
                if (isCreator) {
                    operations.add(MaintenanceOrderOperation.EDIT);
                    operations.add(MaintenanceOrderOperation.SUBMIT);
                }
                break;

            case REVIEWING:
                if (isCreator) {
                    operations.add(MaintenanceOrderOperation.CANCEL);
                }
                if (isAdmin) {
                    operations.add(MaintenanceOrderOperation.CANCEL);
                    operations.add(MaintenanceOrderOperation.REVIEW);
                    operations.add(MaintenanceOrderOperation.REJECT);
                    operations.add(MaintenanceOrderOperation.ROLLBACK); // 退回至 CREATED
                }
                if (isLeadElectrician) {
                    operations.add(MaintenanceOrderOperation.REJECT);
                }
                break;

            case ASSIGNED:
            case REASSIGNED:
            case PROCESSING:
                if (isCreator && !electricianTaskService.existsResolvedTask(order.getId())) { // 判断是否有任何电工任务已解决（防止客户随意取消）
                    operations.add(MaintenanceOrderOperation.CANCEL);
                }
                if (isAdmin || isLeadElectrician) {
                    operations.add(MaintenanceOrderOperation.REASSIGN);
                }
                if (isAdmin) {
                    operations.add(MaintenanceOrderOperation.CANCEL);
                    operations.add(MaintenanceOrderOperation.REJECT);
                }
                if (isLeadElectrician) {
                    operations.add(MaintenanceOrderOperation.REJECT);
                }
                break;

            case RESOLVED:
                if (isCustomer) {
                    operations.add(MaintenanceOrderOperation.EVALUATE);
                }
                if (isAdmin) {
                    operations.add(MaintenanceOrderOperation.ROLLBACK); // 退回至 ASSIGNED
                    operations.add(MaintenanceOrderOperation.COMPLETE);
                }
                break;


            case REJECTED:
            case CANCELLED:
                if (isAdmin) {
                    operations.add(MaintenanceOrderOperation.DELETE);
                }
                break;
            case COMPLETED:
                if (isCustomer) {
                    operations.add(MaintenanceOrderOperation.EVALUATE);
                }
                break;
        }

        return operations;
    }

    @Override
    public Boolean canOperate(String orderId, MaintenanceOrderOperation operation, MaintenanceOrderOperatorRole operatorRole) {
        if (orderId == null || operation == null || operatorRole == null) {
            return false;
        }

        // 系统角色可执行所有操作
        if (MaintenanceOrderOperatorRole.SYSTEM.equals(operatorRole)) {
            return true;
        }

        // 1. 查询工单
        MaintenanceOrder order = this.getById(orderId);
        if (order == null) {
            return false; // 工单不存在
        }

        // 2. 获取当前角色在该状态下的所有可执行操作
        List<MaintenanceOrderOperation> allowedOps = getAvailableOperations(order, operatorRole);

        // 3. 判断目标操作是否在允许列表中
        return allowedOps.contains(operation);
    }

    private Boolean canOperate(String orderId, MaintenanceOrderOperation operation, String operatorRole) {
        return canOperate(orderId, operation, MaintenanceOrderOperatorRole.of(operatorRole));
    }

    /**
     * 工单状态回退映射：key → value 表示 key 状态可退回至 value 状态
     */
    private static final Map<MaintenanceOrderStatus, MaintenanceOrderStatus> ROLLBACK_FLOW = Map.of(
            MaintenanceOrderStatus.REVIEWING, MaintenanceOrderStatus.CREATED,   // 审核中可退回至创建
            MaintenanceOrderStatus.RESOLVED, MaintenanceOrderStatus.ASSIGNED    // 已解决可退回至已分配
    );

    /*----------------------------------------------------------------------------------------------------------------*/

    /*----------------------------------------------------------------------------------------------------------------*/
    /*
     * 工单状态更新
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateStatus(MaintenanceOrderUpdateStatusReqDTO in, Consumer<MaintenanceOrder> additionalUpdater) {
        MaintenanceOrder order = this.getOrderById(in.getOrderId());

        // 设置新状态
        MaintenanceOrderStatus oldStatus = order.getStatus();
        MaintenanceOrderStatus targetStatus = in.getTargetStatus();
        order.setStatus(targetStatus);

        // 根据状态自动设置时间字段
        if (MaintenanceOrderStatus.ASSIGNED.equals(targetStatus)) {
            order.setAssignAt(LocalDateTime.now());
        } else if (MaintenanceOrderStatus.REJECTED.equals(targetStatus)) {
            order.setRejectAt(LocalDateTime.now());
        } else if (MaintenanceOrderStatus.CANCELLED.equals(targetStatus)) {
            order.setCancelAt(LocalDateTime.now());
        } else if (MaintenanceOrderStatus.RESOLVED.equals(targetStatus)) {
            order.setResolveAt(LocalDateTime.now());
        } else if (MaintenanceOrderStatus.COMPLETED.equals(targetStatus)) {
            order.setCompleteAt(LocalDateTime.now());
        }
        // 可根据需要扩展其他状态时间字段

        // 执行额外字段设置（如驳回原因）
        if (additionalUpdater != null) {
            additionalUpdater.accept(order);
        }

        this.updateById(order);

        // 4. 记录流程日志
        processService.create(MaintenanceOrderProcessCreateReqDTO.builder()
                .MaintenanceOrderId(order.getId())
                .action(in.getAction())
                .fromStatus(oldStatus)
                .toStatus(targetStatus)
                .operatorRole(MaintenanceOrderOperatorRole.of(in.getOperatorRole()))
                .operatorId(UserContext.getCurrentUserId())
                .operatorLongitude(in.getOperatorLongitude())
                .operatorLatitude(in.getOperatorLatitude())
                .remarks(in.getRemarks())
                .isCompleted(1)
                .build());

    }

    /*----------------------------------------------------------------------------------------------------------------*/

    /**
     * 客户提交工单（created → reviewing）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<String> submit(MaintenanceOrderSubmitReqDto in) {
        MaintenanceOrder order = this.getOrderById(in.getOrderId());
        if (!canOperate(in.getOrderId(), MaintenanceOrderOperation.SUBMIT, in.getOperatorRole())) {
            throw new IllegalStateException("当前状态不允许提交：" + order.getStatus());
        }

        this.updateStatus(MaintenanceOrderUpdateStatusReqDTO.builder()
                .orderId(in.getOrderId())
                .action(MaintenanceOrderOperation.SUBMIT)
                .targetStatus(MaintenanceOrderStatus.REVIEWING)
                .operatorRole(in.getOperatorRole())
                .operatorLongitude(in.getOperatorLongitude())
                .operatorLatitude(in.getOperatorLatitude())
                .remarks(in.getRemarks())
                .build(), null);
        return ResponseResult.ok("提交成功，进入审核流程");
    }

    /**
     * 管理员审核通过（reviewing → assigned）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<String> review(MaintenanceOrderReviewReqDto in) {
        MaintenanceOrder order = this.getOrderById(in.getOrderId());
        if (!canOperate(in.getOrderId(), MaintenanceOrderOperation.REVIEW, in.getOperatorRole())) {
            throw new IllegalStateException("无权限审核或状态不允许：" + order.getStatus());
        }

        // 创建电工任务
        electricianTaskService.createTasks(in.getElectricians());

        this.updateStatus(MaintenanceOrderUpdateStatusReqDTO.builder()
                .orderId(in.getOrderId())
                .action(MaintenanceOrderOperation.REVIEW)
                .targetStatus(MaintenanceOrderStatus.ASSIGNED)
                .operatorRole(in.getOperatorRole())
                .operatorLongitude(in.getOperatorLongitude())
                .operatorLatitude(in.getOperatorLatitude())
                .remarks(in.getRemarks())
                .build(), o -> {
            o.setElectricianId(in.getLeadElectricianId());
        });

        return ResponseResult.ok("审核通过，工单已分配");
    }

    /**
     * 驳回工单（ → rejected）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<String> reject(MaintenanceOrderRejectReqDto in) {
        MaintenanceOrder order = this.getOrderById(in.getOrderId());
        if (!this.canOperate(in.getOrderId(), MaintenanceOrderOperation.REJECT, in.getOperatorRole())) {
            throw new IllegalStateException("当前状态不允许驳回");
        }
        this.updateStatus(MaintenanceOrderUpdateStatusReqDTO.builder()
                .orderId(in.getOrderId())
                .action(MaintenanceOrderOperation.REJECT)
                .targetStatus(MaintenanceOrderStatus.REJECTED)
                .operatorRole(in.getOperatorRole())
                .operatorLongitude(in.getOperatorLongitude())
                .operatorLatitude(in.getOperatorLatitude())
                .remarks(in.getRemarks())
                .build(), o -> {
            o.setRejectReason(in.getRemarks());
        });

        // 清理相关任务
        electricianTaskService.updateStatusByOrderId(
                order.getId(),
                MaintenanceOrderElectricianTaskStatus.CANCELLED,
                MaintenanceOrderElectricianTaskOperation.REJECT,
                "驳回工单时同步取消未解决的任务");
        return ResponseResult.ok("驳回成功");
    }

    /**
     * 退回工单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<String> rollback(MaintenanceOrderRollbackReqDto in) {
        MaintenanceOrder order = this.getOrderById(in.getOrderId());
        if (!canOperate(in.getOrderId(), MaintenanceOrderOperation.ROLLBACK, in.getOperatorRole())) {
            throw new IllegalStateException("当前状态或用户无权限执行退回操作" + order.getStatus());
        }

        MaintenanceOrderStatus currentStatus = order.getStatus();

        // 获取上一步状态
        MaintenanceOrderStatus previousStatus = ROLLBACK_FLOW.get(currentStatus);
        if (previousStatus == null) {
            throw new IllegalStateException("当前状态不支持退回" + order.getStatus());
        }

        // 特殊处理：退回时的业务逻辑
        handleRollbackBusinessLogic(order, currentStatus, previousStatus);

        // 更新状态
        this.updateStatus(MaintenanceOrderUpdateStatusReqDTO.builder()
                .orderId(order.getId())
                .action(MaintenanceOrderOperation.ROLLBACK)
                .targetStatus(previousStatus)
                .operatorRole(in.getOperatorRole())
                .operatorLongitude(in.getOperatorLongitude())
                .operatorLatitude(in.getOperatorLatitude())
                .remarks(in.getRemarks())
                .build(), null);

        return ResponseResult.ok("退回成功！");
    }

    /**
     * 处理退回时的关联业务（如取消任务、重置字段等）
     */
    private void handleRollbackBusinessLogic(MaintenanceOrder order,
                                             MaintenanceOrderStatus currentStatus,
                                             MaintenanceOrderStatus previousStatus) {

    }

    /*----------------------------------------------------------------------------------------------------------------*/

    /**
     * 重新分配电工（处理拒单或调整）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<String> reassign(MaintenanceOrderAssignReqDto in) {
        MaintenanceOrder order = this.getOrderById(in.getOrderId());
        if (!canOperate(in.getOrderId(), MaintenanceOrderOperation.REASSIGN, in.getOperatorRole())) {
            throw new IllegalStateException("当前状态不允许重新分配电工：" + order.getStatus());
        }

        // 如果主修电工改变，则需要修改工单中的electricianId
        if (!order.getElectricianId().equals(in.getLeadElectricianId())) {
            order.setElectricianId(in.getLeadElectricianId());
            this.updateById(order);
        }

        // 重新创建电工任务
        electricianTaskService.createTasks(in.getElectricians());

        // 如果工单状态是 assigned，更新工单状态为 reassigned；否则保持状态
        if (MaintenanceOrderStatus.ASSIGNED.equals(order.getStatus()) || MaintenanceOrderStatus.REASSIGNED.equals(order.getStatus())) {
            this.updateStatus(MaintenanceOrderUpdateStatusReqDTO.builder()
                    .orderId(in.getOrderId())
                    .action(MaintenanceOrderOperation.REASSIGN)
                    .targetStatus(MaintenanceOrderStatus.REASSIGNED)
                    .operatorRole(in.getOperatorRole())
                    .operatorLongitude(in.getOperatorLongitude())
                    .operatorLatitude(in.getOperatorLatitude())
                    .remarks(in.getRemarks())
                    .build(), null);
        }
        // 如果工单状态是 processing，保持状态

        return ResponseResult.ok("重新分配电工成功！");
    }

    /**
     * 工单处理完成（resolved → cancelled）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<String> complete(MaintenanceOrderCompleteReqDto in) {
        MaintenanceOrder order = this.getOrderById(in.getOrderId());
        if (!canOperate(in.getOrderId(), MaintenanceOrderOperation.COMPLETE, in.getOperatorRole())) {
            throw new IllegalStateException("当前状态不允许完成：" + order.getStatus());
        }
        this.updateStatus(MaintenanceOrderUpdateStatusReqDTO.builder()
                .orderId(in.getOrderId())
                .action(MaintenanceOrderOperation.COMPLETE)
                .targetStatus(MaintenanceOrderStatus.COMPLETED)
                .operatorRole(in.getOperatorRole())
                .operatorLongitude(in.getOperatorLongitude())
                .operatorLatitude(in.getOperatorLatitude())
                .remarks(in.getRemarks())
                .build(), null);
        return ResponseResult.ok("处理完成");
    }

    /**
     * 取消工单（→ cancelled）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<String> cancel(MaintenanceOrderCancelReqDto in) {
        MaintenanceOrder order = this.getOrderById(in.getOrderId());
        if (!canOperate(in.getOrderId(), MaintenanceOrderOperation.CANCEL, in.getOperatorRole())) {
            throw new IllegalStateException("当前状态不允许取消：" + order.getStatus());
        }
        this.updateStatus(MaintenanceOrderUpdateStatusReqDTO.builder()
                .orderId(in.getOrderId())
                .action(MaintenanceOrderOperation.CANCEL)
                .targetStatus(MaintenanceOrderStatus.CANCELLED)
                .operatorRole(in.getOperatorRole())
                .operatorLongitude(in.getOperatorLongitude())
                .operatorLatitude(in.getOperatorLatitude())
                .remarks(in.getRemarks())
                .build(), o -> {
            o.setCancelReason(in.getRemarks());
        });

        // 取消所有未完成的电工任务
        electricianTaskService.updateStatusByOrderId(
                order.getId(),
                MaintenanceOrderElectricianTaskStatus.CANCELLED,
                MaintenanceOrderElectricianTaskOperation.CANCEL,
                "取消工单时同步取消未解决的任务");

        return ResponseResult.ok("取消成功！");
    }

    /**
     * 根据所有工单电工任务状态，同步工单主状态
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncOrderStatus(String orderId) {
        MaintenanceOrder order = this.getOrderById(orderId);
        MaintenanceOrderStatus newOrderStatus = electricianTaskService.calculateOrderStatus(order);
        if (!order.getStatus().equals(newOrderStatus)) {
            this.updateStatus(MaintenanceOrderUpdateStatusReqDTO.builder()
                    .orderId(orderId)
                    .action(MaintenanceOrderOperation.SYSTEM_SYNC_STATUS)
                    .targetStatus(newOrderStatus)
                    .operatorRole(MaintenanceOrderOperatorRole.SYSTEM.getCode())
                    .build(), null);
        }
    }

    /* *********************************************************************
     * 分页与条件查询
     ********************************************************************* */

    @Override
    public ResponseResult<Page<MaintenanceOrder>> pageQuery(MaintenanceOrderPageListReqDTO in) {
        Page<MaintenanceOrder> page = new Page<>(in.getPageNum(), in.getPageSize());
        LambdaQueryWrapper<MaintenanceOrder> wrapper = new LambdaQueryWrapper<>();
        if (in.getStatus() != null && !in.getStatus().isEmpty()) {
            wrapper.eq(MaintenanceOrder::getStatus, in.getStatus());
        }
        if (in.getPriority() != null && !in.getPriority().isEmpty()) {
            wrapper.eq(MaintenanceOrder::getPriority, in.getPriority());
        }
        if (in.getType() != null && !in.getType().isEmpty()) {
            wrapper.eq(MaintenanceOrder::getType, in.getType());
        }
        if (in.getCustomerId() != null && !in.getCustomerId().isEmpty()) {
            wrapper.eq(MaintenanceOrder::getCustomerId, in.getCustomerId());
        }
        if (in.getElectricianId() != null && !in.getElectricianId().isEmpty()) {
            wrapper.eq(MaintenanceOrder::getElectricianId, in.getElectricianId());
        }
        if (in.getEquipmentId() != null && !in.getEquipmentId().isEmpty()) {
            wrapper.eq(MaintenanceOrder::getEquipmentId, in.getEquipmentId());
        }
        if (in.getKeyword() != null && !in.getKeyword().isEmpty()) {
            wrapper.and(w -> w.like(MaintenanceOrder::getTitle, in.getKeyword())
                    .or()
                    .like(MaintenanceOrder::getDescription, in.getKeyword()));
        }
        if (in.getStartTime() != null) {
            wrapper.ge(MaintenanceOrder::getCreatedAt, in.getStartTime());
        }
        if (in.getEndTime() != null) {
            wrapper.le(MaintenanceOrder::getCreatedAt, in.getEndTime());
        }
        return ResponseResult.ok(this.baseMapper.selectPage(page, wrapper));
    }

    @Override
    public MaintenanceOrderDetailRespDto detail(String id) {
        MaintenanceOrder order = this.getOrderById(id);

        // 查询主流程日志
        List<MaintenanceOrderProcess> processes = processService.getProcessHistory(id);

        // 查询关联电工任务
        List<MaintenanceOrderElectricianTask> tasks = electricianTaskService.listByOrderId(id);

        return MaintenanceOrderDetailRespDto.builder()
                .order(order)
                .electricianTasks(tasks)
                .processHistory(processes)
                .build();
    }

    /* *********************************************************************
     * 统计与报表
     ********************************************************************* */

    @Override
    public ResponseResult<Map<String, Long>> countByStatus() {
        return ResponseResult.ok(this.baseMapper.countByStatus());
    }

    @Override
    public ResponseResult<Long> countInRange(LocalDateTime startTime, LocalDateTime endTime) {
        LambdaQueryWrapper<MaintenanceOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(MaintenanceOrder::getCreatedAt, startTime)
                .le(MaintenanceOrder::getCreatedAt, endTime);
        return ResponseResult.ok(this.baseMapper.selectCount(wrapper));
    }

    @Override
    public ResponseResult<List<MaintenanceOrder>> listOverdueOrders(long thresholdHours) {
        LocalDateTime threshold = LocalDateTime.now().minusHours(thresholdHours);
        LambdaQueryWrapper<MaintenanceOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MaintenanceOrder::getIsDeleted, 0)
                .in(MaintenanceOrder::getStatus, Arrays.asList(MaintenanceOrderStatus.CREATED, MaintenanceOrderStatus.ASSIGNED))
                .lt(MaintenanceOrder::getCreatedAt, threshold);
        return ResponseResult.ok(this.baseMapper.selectList(wrapper));
    }

    /* *********************************************************************
     * 自动任务
     ********************************************************************* */

    @Scheduled(fixedDelay = 3600000) // 每小时执行一次
    @Transactional
    public void handleAutoAssign() {
        log.trace("开始执行维保工单自动分配任务...");

        LocalDateTime timeoutThreshold = LocalDateTime.now().minusHours(sysFeignService.getAssignTimeoutHours());

        // 查找创建时间早于阈值、且仍未分配的工单（status in [reviewing]）
        List<MaintenanceOrder> candidates = this.baseMapper.selectList(new LambdaQueryWrapper<MaintenanceOrder>()
                .eq(MaintenanceOrder::getStatus, MaintenanceOrderStatus.REVIEWING)
                .lt(MaintenanceOrder::getCreatedAt, timeoutThreshold)
                .isNull(MaintenanceOrder::getAssignAt) // 尚未分配
        );

        for (MaintenanceOrder order : candidates) {
            try {
                // 自动分配逻辑
                String assignedElectricianId = autoAssignElectrician(order);
                if (assignedElectricianId != null && !assignedElectricianId.isEmpty() && !StringUtils.isBlank(assignedElectricianId)) {
                    this.review(MaintenanceOrderReviewReqDto.builder()
                            .orderId(order.getId())
                            .operatorRole(MaintenanceOrderOperatorRole.SYSTEM.getCode())
                            .LeadElectricianId(assignedElectricianId)
                            .electricians(List.of(MaintenanceOrderElectricianTaskCreateReqDTO.builder()
                                    .maintenanceOrderId(order.getId())
                                    .electricianId(assignedElectricianId)
                                    .responsibility("")  // 若可省略或设默认值，可优化
                                    .operatorRole(MaintenanceOrderOperatorRole.SYSTEM.getCode())
                                    .remarks("")
                                    .build()))
                            .remarks("维保工单超时自动分配")
                            .build());

                    log.trace("维保工单 " + order.getId() + " 已自动分配给电工 " + assignedElectricianId);
                }
            } catch (Exception e) {
                log.error("自动分配维保工单 " + order.getId() + " 失败", e);
            }
        }
    }

    /**
     * 自动分配电工
     * 优先分配：负责当前客户的空闲电工（专属电工）。
     * 次优分配：若无专属空闲电工，则分配给当前区域内待处理工单最少的电工。
     * 公平分配：若工单数相同，则随机分配。
     * 兜底策略：若区域内无可用电工，则通知管理员。
     */
    private String autoAssignElectrician(MaintenanceOrder order) {
        String customerId = order.getCustomerId();
        User customer = sysFeignService.getUserInfoById(customerId);
        if (customer == null) {
            String message = String.format("【紧急】维保工单ID：%s 自动分配失败，客户：%s 信息有误。请管理员手动分配。", order.getId(), order.getCustomerId());
            log.error(message);
            notifyAdmin(order, message);
            return null;
        }

        String regionId = customer.getOrgId();

        // 1. 查找负责该客户的专属且空闲的电工
        String assignedElectricianId = findDedicatedIdleElectrician(customer);
        if (assignedElectricianId != null) {
            log.trace("为维保工单 " + order.getId() + " 分配专属空闲电工: " + assignedElectricianId);
            return assignedElectricianId;
        }

        // 2. 查找本区域内工单最少的空闲电工
        assignedElectricianId = findLeastBusyElectricianInRegion(regionId);
        if (assignedElectricianId != null) {
            log.trace("为工单 " + order.getId() + " 分配区域最低负载电工: " + assignedElectricianId);
            return assignedElectricianId;
        }

        // 3. 区域内无可用电工
        handleNoElectricianAvailable(order, regionId);
        return null;
    }

    /**
     * 查找负责该客户的专属且空闲的电工
     */
    private String findDedicatedIdleElectrician(User customer) {
        // 查询专属电工
        List<String> dedicatedIds = sysFeignService.getDedicatedElectricianByCustomer(customer);
        if (dedicatedIds == null || dedicatedIds.isEmpty()) {
            return null;
        }
        // TODO: 待完善家庭关联多个电工逻辑
        return dedicatedIds.get(0);
    }

    /**
     * 查找本区域内工单最少的空闲电工（工单数相同则随机）
     */
    private String findLeastBusyElectricianInRegion(String regionId) {
        // 查询本区域内所有空闲电工
        List<String> idleElectricians = sysFeignService.getElectriciansByOrgId(regionId);

        if (idleElectricians.isEmpty()) {
            return null;
        }

        // 统计每个电工的待处理工单数
        Map<String, Long> workloadMap = electricianTaskService.incompleteTaskCountByElectrician();

        // 找出工单最少的电工（支持并列）
        Long minWorkload = workloadMap.values().stream().min(Long::compareTo).orElse(0L);
        List<String> candidates = workloadMap.entrySet().stream()
                .filter(e -> e.getValue().equals(minWorkload))
                .map(Map.Entry::getKey)
                .toList();

        // 随机选择一个
        Random random = new Random();
        return candidates.get(random.nextInt(candidates.size()));
    }

    /**
     * 判断电工是否空闲 TODO
     */
    private boolean isElectricianIdle(ElectricianArchives electrician) {
        return true;
    }

    /**
     * 处理无可用电工的情况：通知管理员
     */
    private void handleNoElectricianAvailable(MaintenanceOrder order, String regionId) {
        String message = String.format(
                "【紧急】区域 %s 内无可用电工处理工单！维保工单ID：%s，客户：%s。请管理员手动分配。",
                regionId, order.getId(), order.getCustomerId()
        );
        log.warn(message);
        this.notifyAdmin(order, message);
    }

    private void notifyAdmin(MaintenanceOrder order, String message) {
        // 获取管理员ID
        List<String> recipientIds = sysFeignService.getAdminIds();
        if (recipientIds == null || recipientIds.isEmpty()) {
            return;
        }

        // 创建通知
        for (String recipientId : recipientIds) {
            OrderNotificationCreateReqDTO OrderNotificationCreateReqDTO = new OrderNotificationCreateReqDTO();
            OrderNotificationCreateReqDTO.setOrderType(order.getType().getCode());
            OrderNotificationCreateReqDTO.setOrderId(order.getId());
            OrderNotificationCreateReqDTO.setRecipientId(recipientId);
            OrderNotificationCreateReqDTO.setRecipientRole(MaintenanceOrderOperatorRole.ADMIN.getCode());
            OrderNotificationCreateReqDTO.setNotificationType(OrderNotificationType.IN_SYSTEM.getCode());
            OrderNotificationCreateReqDTO.setContent(message);
            orderNotificationService.create(OrderNotificationCreateReqDTO);
        }
    }

    @Scheduled(fixedDelay = 3600000) // 每小时执行一次（完成检查频率可低些）
    @Transactional
    public void handleAutoComplete() {
        log.trace("开始执行维保工单自动完成任务...");

        LocalDateTime timeoutThreshold = LocalDateTime.now().minusHours(sysFeignService.getCompleteTimeoutHours());

        // 查找 resolved 状态且超过确认时限的工单
        List<MaintenanceOrder> candidates = this.baseMapper.selectList(new LambdaQueryWrapper<MaintenanceOrder>()
                .eq(MaintenanceOrder::getStatus, MaintenanceOrderStatus.RESOLVED)
                .eq(MaintenanceOrder::getIsDeleted, 0)
                .lt(MaintenanceOrder::getResolveAt, timeoutThreshold) // 假设 resolveAt 是处理完成时间
                .isNull(MaintenanceOrder::getCompleteAt)
        );

        for (MaintenanceOrder order : candidates) {
            try {
                this.complete(MaintenanceOrderCompleteReqDto.builder()
                        .orderId(order.getId())
                        .operatorRole(MaintenanceOrderOperatorRole.SYSTEM.getCode())
                        .remarks("维保工单超时自动完成")
                        .build());

                log.trace("工单 " + order.getId() + " 已自动完成");
            } catch (Exception e) {
                log.error("自动完成维保工单 " + order.getId() + " 失败", e);
            }
        }
    }
}